<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>输入框输入打字放大特效</title>
  <style>
    * {
      /* 初始化 */
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      /* 方便演示 */
      display: flex;
      height: 100vh;
      align-items: center;
      justify-content: center;
      /* 背景渐变 */
      background: linear-gradient(to bottom, #6a85b6, #bac8e0);
      /* 溢出隐藏 */
      overflow: hidden;
    }
    h1 {
      color: #fff;
      text-align: center;
    }
    .input-box {
      position: relative;
    }
    .input-box input {
      /* 隐藏原生输入框 */
      opacity: 0;
    }
    .input-box label {
      min-width: 100%;
      min-height: 40px;
      background-color: #fff;
      /* 弹性布局 */
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 4px;
      padding: 0 10px;
      cursor: text;
      /* 过渡 */
      transition: 0.2s;
    }
    /* input聚焦时触发 */
    .input-box input:focus ~ label {
      box-shadow: 0 5px 20px #6a85b6; 
    }
    .input-box span {
      font-size: 16px;
      font-weight: bold;
    }
    .input-animate {
      /* 打字动画, 动画名 时长  加速后减速 */
      animation: print 0.2s ease-in-out;
    }
    .shake {
      /* 输入框颤动动画 */
      animation: shake 0.2s ease-in-out;
    }
    /* 定义动画 */

    /* 打字动画 */
    @keyframes print {
      0% {
        position: absolute;
        transform: scale(50);
      }
      99% {
        position: absolute;
      }
      100% {
        position: relative;
      }
    }
    /* 输入框颤动动画 */
    @keyframes shker {
      50% {
        transform: scale(0.95);
      }
    }
  </style>
</head>
<body>
  <div class="container"></div>
    <template id="my-vue">
      <h1>输入框打字特效</h1>
      <div class="input-box">
        <!-- 当input和label相关联时,关联标签的表单控件称为这个标签的已关联标签的控件。一个 input 可以与多个标签相关联 -->
        <!-- 点击或者轻触（tap）与表单控件相关联的 <label> 也可以触发关联控件的 click 事件。 -->
        <input type="text" id="txtMessage" v-model="message">
        <label for="txtMessage">
          <span class="input-animate" v-for="item in message2">{{item}}</span>
        </label>
      </div>
    </template>
</body>
<script src='https://unpkg.com/vue@next '></script>
<script>
  const vm = {
    template: '#my-vue',
    data() {
      return {
        message: ''
      }
    },
    computed: {
      message2() {
        // 把输入框的文字拆分为单子
        return this.message.split('');
      }
    },
    watch: {
      //  监听输入框的文字，来实现输入框的颤动动画
      message: {
        handler(newValue, oldValue) {
          // 如果文字有变化
          if (newValue.length > oldValue.length) {
            setTimeout(() => {
              document.querySelector('.input-box').classList.add('shake');
              setTimeout(() => {
                document.querySelector('.input-box').classList.remove('shake');
              }, 300)
            }, 200)
          }
        }
      }
    }
  }
  Vue.createApp(vm).mount('.container');
</script>
</html>